﻿using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.CV.UI;
using PipeDetection.Model;
using PipeDetection.Repository;
using PipeDetection.UI.接口;
using Sunny.UI;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Collections.Specialized.BitVector32;

namespace PipeDetection.UI
{
    public partial class FrmDetectionFlag : UIPage,Ipage
    {
        public FrmDetectionFlag()
        {
            InitializeComponent();
            InitButtons();
        }

        public event EventHandler PropertyChanged;

        private int curfrm;
        private IImage img;

        private float station;
        private List<Point> limits;
        private List<Point> leftlim;
        private List<Point> rightlim;
        private List<List<Point>> fzLines;
        private DefectCatalog defect1 = new DefectCatalog()
        {
            GeometryType = Gtype.箭头,
            ColorOfPorL = Color.White,
            LineType = Ltype.实线,
            HatchPattern=Hpattern.填充,
            LineWidth=Lwidth.粗
        };
        private DefectCatalog defect2 = new DefectCatalog()
        {
            GeometryType = Gtype.线,
            ColorOfPorL = Color.White,
            LineType = Ltype.虚线,
            LineWidth = Lwidth.中等
        };
        private DefectCatalog defect3 = new DefectCatalog()
        {
            GeometryType = Gtype.线,
            ColorOfPorL = Color.Red,
            LineType = Ltype.虚线,
            LineWidth = Lwidth.中等
        };
        private bool issaved = false;
        public void InitD(object obj)
        {
            //参数，当前帧，图像
            var pars = (object[])obj;
            curfrm = (int)pars[0];
            leftlim = null;
            rightlim = null;
            limits = null;
            fzLines = null;
            issaved = false;
            uiButton4.Enabled = true;
            uiButton1.Enabled  = true;
            defectOlst.Clear();
            img = (IImage)pars[1];
            uiComboBox1.SelectedIndex = 0;
            CutImg();

            //todo:识别里程，标注线等
            ScanOcr();

        }

        private void ScanOcr()
        {
            var str = EmguCvHelper.OCR((Bitmap)pictureBox2.Image);
            var regx = new System.Text.RegularExpressions.Regex("([\\d.]+)\\s*m");
            if (regx.IsMatch(str))
            {
                var math = regx.Match(str);
                station = Convert.ToSingle(math.Groups[1].Value);
                uiDigitalLabel1.Value = station;
                uiLabel2.Text = $"里程：{station}m";
                uiDoubleUpDown1.Value = station;
                //uiTitlePanel1.Visible = false;
            }
            else
            {
                //uiTitlePanel1.Visible = true;
                uiLabel2.Text = $"里程：未识别请输入";
            }
            //识别边线
            var pts = EmguCvHelper.FindEdge(image1.Clone());
            if (pts != null)
            {
                  limits = pts;
            }

            ReDrawBaseInfo();

        }
        private void ReDrawBaseInfo()
        {
            var img = image1.Clone().ToBitmap();
            float ang;
          if(limits != null)
            {

                Common.DrawSymbol(defect1, img, new List<Point>() { limits[1], limits[0] });
                Common.DrawSymbol(defect1, img, new List<Point>() { limits[1], limits[2] });
                 ang = (float)(Drawing.CalcAngle(limits[0], limits[1]) + 90);
                Common.LabImg(img, "量程（m）", Color.White, Drawing.CalcAzRangePoint(limits[0], 50, ang, -15, -15), ang - 90);
                ang = (float)(Drawing.CalcAngle(limits[2], limits[1]) - 90);
                Common.LabImg(img, "量程（m）", Color.White, Drawing.CalcAzRangePoint(limits[2], 50, ang, 15, -5), ang + 90);
            }
        
            //标注   里程（m）
            var s = Globel.pipeSectionInspection.RovPosition == Rpositon.顶部 ? "管顶" : $"{Globel.pipeSectionInspection.RovPosition}壁";
            var p1 = new PointF(s.Length * 16, 20);
            var p2=p1.Clone();
            Common.LabImg(img, s, Color.White, p1, 0);

            if (station > 0)
            {
                s = $"潜水器位置{station:f1}m";
                p1 = new PointF(img.Width - s.Length * 16, 20);
                Common.LabImg(img, s, Color.White, p1, 0);
                uiLabel2.Text = $"里程：{station}m";
            }

            if (leftlim != null)
            {
                Common.DrawSymbol(defect2, img, leftlim);
                ang = (float)(Drawing.CalcAngle(leftlim[0], leftlim[1]) - 90);
                p1 = Common.GetCenter(leftlim);
                if (Globel.pipeSectionInspection.RovPosition == Rpositon.顶部) s = "左侧壁";
                else if (Globel.pipeSectionInspection.RovPosition == Rpositon.左侧) s = "管底线";
                else s = "拱顶线";
                p2 = p1 + new Size(-30, -25);
                Common.LabImg(img, s.Substring(0,1), Color.White, p2, 0, 20);
                p2 = p1 + new Size(-30, 0);
                Common.LabImg(img, s.Substring(1,1), Color.White, p2, 0 ,20);
                p2 = p1 + new Size(-30, 25);
                Common.LabImg(img, s.Substring(2, 1), Color.White, p2, 0, 20);

            }
      
            if(rightlim!=null)
            {
                Common.DrawSymbol(defect2, img, rightlim);
                ang = (float)(Drawing.CalcAngle(rightlim[0], rightlim[1]) + 90);
                p1 = Common.GetCenter(rightlim);
                if (Globel.pipeSectionInspection.RovPosition == Rpositon.顶部) s = "右侧壁";
                else if (Globel.pipeSectionInspection.RovPosition == Rpositon.左侧) s = "拱顶线";
                else s = "管底线";
                p2 = p1 + new Size(30, -25);
                Common.LabImg(img, s.Substring(0, 1), Color.White, p2, 0, 20);
                p2 = p1 + new Size(30, 0);
                Common.LabImg(img, s.Substring(1, 1), Color.White, p2, 0, 20);
                p2 = p1 + new Size(30, 25);
                Common.LabImg(img, s.Substring(2, 1), Color.White, p2, 0, 20);

            }


            if (fzLines != null)
            {
                foreach (var item in fzLines)
                {
                    Common.DrawSymbol(defect3,img,item);
                }
            }


            pictureBox1.Image = img;
            UpdateOservs();
        }

        private void UpdateOservs()
        {
            foreach (var item in defectOlst)
            {
                oservations = item;
                UpdateOserv(null, null);
            }
        }

        private void InitButtons()
        {
            var dcs = Globel.DefectCatalogRepository.Query();
            foreach (var d in dcs)
            {
                UIHeaderButton btn = new UIHeaderButton
                {
                    Size=new Size(37+18*d.DefectCatalogName.Length,40),
                    Text = d.DefectCatalogName,
                    Tag = d,
                    SymbolSize=40,
                    SymbolColor=Color.Red,
                    CircleSize=40,
                    Image = d.IconOfButton,
                    TextAlign = ContentAlignment.MiddleRight,
                    ImageTop = 2,
                    TextImageRelation = TextImageRelation.ImageBeforeText
                };
                btn.Click += Btn_Click;
                if (d.IconOfButton == null)
                {
                    if (d.GeometryType == Gtype.点) btn.Symbol = 61842;
                    if (d.GeometryType == Gtype.线) btn.Symbol = 559682;
                    if (d.GeometryType == Gtype.面) btn.Symbol = 362958;
                    if (d.GeometryType == Gtype.箭头) btn.Symbol = 357495;
                    if (d.GeometryType == Gtype.方向线) btn.Symbol = 561612;

                }
                btn.SetStyleColor(UIStyles.Orange);
                uiFlowLayoutPanel2.Controls.Add(btn);
            }


        }
        //备用，防备存在多个缺陷
        private List<DefectOservations> defectOlst = new List<DefectOservations>();
        //当前缺陷
        private DefectOservations oservations = null;

        //缺陷按钮

        private void Btn_Click(object sender, EventArgs e)
        {

            //判断  如果未定义分辨率需选定义，否则影响后面的标注计算尺寸
            if (Globel.pipeSectionInspection.resolution == 0)
            {
                UIMessageBox.Show("请先定义分辨率后再标注，否则影响尺寸计算", true);
                return;
            }
            if(leftlim ==null || rightlim == null)
            {
                UIMessageBox.Show("请先定义界线，否则影响尺寸计算", true);
                return;
            }

            DefectCatalog d = (DefectCatalog)((UIHeaderButton)sender).Tag;
           
            pictureBox4.Image = pictureBox1.Image;
            var q1 = DrawHelper.GetPoints(d, pictureBox4);
            oservations = new DefectOservations();
            UpdateOserv(d, q1);
            defectOlst.Add(oservations);
            DrawOservation(oservations);
            
        }
        /// <summary>
        /// 更新缺陷信息
        /// </summary>
        /// <param name="d"></param>
        /// <param name="q1"></param>
        private void UpdateOserv(DefectCatalog d, List<Point> q1=null)
        {
           
            if (d != null && q1!=null)
            {
                oservations.DefectCatalogId = d.Id;
                oservations.DefectCatalogName = d.DefectCatalogName;
                //todo:计算长宽
                if (d.GeometryType == Gtype.线 )
                {
                    oservations.Length = Common.GetLenght(q1) * Globel.pipeSectionInspection.resolution;
                }
                else if(d.GeometryType==Gtype.面 )
                {
                    oservations.Length = Common.GetHeight(q1) * Globel.pipeSectionInspection.resolution;
                    oservations.Area=Common.GetArea(q1) *Globel.pipeSectionInspection.resolution * Globel.pipeSectionInspection.resolution;
                }


                oservations.Geometry = q1;
                oservations.Stationing = station;
                oservations.Width = Common.GetWidth(q1) * Globel.pipeSectionInspection.resolution;
                oservations.Start = station + Common.GetMinDist(q1, limits[1]) * Globel.pipeSectionInspection.resolution + Globel.pipeSection.C1;
                //两种计算方法，另一种直接用start + Length,因为length可能为线长,所以这里用。。。
                oservations.End = station + Common.GetMaxDist(q1, limits[1]) * Globel.pipeSectionInspection.resolution + Globel.pipeSection.C1;


            }
            if (station != oservations.Stationing)
            {
                oservations.Start = oservations.Start - oservations.Stationing + station;
                oservations.End=oservations.End- oservations.Stationing + station;
                oservations.Stationing = station;
            }
           
            oservations.FpsInVideo = curfrm;
            oservations.PipeSectionInspectionId = Globel.pipeSectionInspection.Id;
           


            oservations.LcR = limits;
            oservations.LeftLimit = leftlim;
            oservations.RightLimit = rightlim;



        }
        private Image<Bgr, byte> image1;
        private Image<Bgr, byte> image2;
        private Image<Bgr, byte> image3;
        private void CutImg()
        {
            defectOlst.Clear();
            uiLabel1.Text = $"视频时间：{TimeSpan.FromSeconds((float)curfrm/Globel.pipeSectionInspection.Fps)}";
            Image<Bgr, byte> image = new Image<Bgr, byte>(img.Bitmap);
            image1= image.GetSubRect(Globel.pipeSectionInspection.DefectRect); pictureBox1.Image = image1.ToBitmap();
            image2 = image.GetSubRect(Globel.pipeSectionInspection.StaTionRect); pictureBox2.Image=image2.ToBitmap();
            image3 = image.GetSubRect(Globel.pipeSectionInspection.SectionRect); pictureBox3.Image=image3. ToBitmap();
            image.Dispose();
        }

        private void uiButton1_Click(object sender, EventArgs e)
        {
            //定义线符号
            pictureBox4.Image = pictureBox1.Image;

            leftlim = DrawHelper.GetPoints(defect2, pictureBox4);
            //uiButton1.Enabled = false;
                 //画到原图
            ReDrawBaseInfo();


        }

        private void uiButton3_Click(object sender, EventArgs e)
        {
            if (oservations != null)
            {
                if (issaved) Globel.DefectOservationsRepository.Update(defectOlst);
                else
                {
                    Globel.DefectOservationsRepository.Add(defectOlst);
                    issaved = true;
                }
                if (Globel.pipeSectionInspection.OutDir != "" && System.IO.Directory.Exists(Globel.pipeSectionInspection.OutDir))
                {
                    pictureBox1.Image.Save($"{Globel.pipeSectionInspection.OutDir}\\L_{oservations.DefectCatalogName}_{oservations.Start:f2}m.png", System.Drawing.Imaging.ImageFormat.Png);
                   // pictureBox2.Image.Save($"{Globel.pipeSectionInspection.OutDir}\\L_station_{curfrm}.png", System.Drawing.Imaging.ImageFormat.Png);
                    pictureBox3.Image.Save($"{Globel.pipeSectionInspection.OutDir}\\L_section_{curfrm}.png", System.Drawing.Imaging.ImageFormat.Png);
                }
                UIMessageBox.ShowSuccess("保存完成", true, 5);

            }
            else
            {
                UIMessageBox.ShowInfo("请标注完全后再保存！",true,5);
            }
     
          
        }

        private void uiButton5_Click(object sender, EventArgs e)
        {
            //定义线符号
            pictureBox4.Image = pictureBox1.Image;
            var q1 = DrawHelper.GetPoints(defect1, pictureBox4);//  dh.GetGeomerty(defect);
       
            var l = 0d;
            if (UIInputDialog.ShowInputDoubleDialog(this, ref l, 2, true, "输入对应实际距离:", true))
            {
                Globel.pipeSectionInspection.resolution = (float)(l / Common.GetDist(q1));
                PropertyChanged?.Invoke(this,EventArgs.Empty);
            }
      
        }

        private void uiButton4_Click(object sender, EventArgs e)
        {
            //定义线符号
            pictureBox4.Image = pictureBox1.Image;
            rightlim = DrawHelper.GetPoints(defect2, pictureBox4);
            //画到原图
            ReDrawBaseInfo();
        }

        private void uiButton2_Click(object sender, EventArgs e)
        {
            if (fzLines == null) fzLines = new List<List<Point>>();
            pictureBox4.Image = pictureBox1.Image;
            var fzl= DrawHelper.GetPoints(defect3, pictureBox4);
            fzLines.Add(fzl);
            //画到原图
            ReDrawBaseInfo();
            foreach (var item in defectOlst)
            {
                DrawOservation(item);
            }
        }

        private void uiButton6_Click(object sender, EventArgs e)
        {
            ((UIForm)this.ParentForm).RemovePage(this.PageIndex);
        }

        private void uiButton7_Click(object sender, EventArgs e)
        {
          pictureBox3.Image= EmguCvHelper.FindEdgeTest(image3.Clone());
  
            

        }

        private void uiDoubleUpDown1_ValueChanged(object sender, double value)
        {
            station = (float)uiDoubleUpDown1.Value;
            ReDrawBaseInfo();
            foreach (var item in defectOlst)
            {
                DrawOservation(item);
            }

        }

        private void DrawOservation(DefectOservations item)
        {
            DefectCatalog d = Globel.DefectCatalogRepository.QueryByKey(item.DefectCatalogId);
            Common.DrawSymbol(d, (Bitmap)pictureBox1.Image, item.Geometry);
            //添加标注
            Common.LabImg(item, d, (Bitmap)pictureBox1.Image);
        }

        private void uiComboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if(oservations!=null)
            {
                oservations.Grade = Convert.ToInt32(uiComboBox1.Text);
                //UpdateOserv(null,null);
                ReDrawBaseInfo();
                foreach (var item in defectOlst)
                {
                    DrawOservation(item);
                }
            }
        }
    }
}
